package com.ccteam.fluidmusic.utils

import android.text.format.DateUtils
import com.ccteam.fluidmusic.view.bean.LyricsBodyItem
import com.ccteam.fluidmusic.view.bean.LyricsStringItem
import com.ccteam.shared.result.BaseItemData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.regex.Pattern


/**
 * @author Xiaoc
 * @since 2021/2/26
 *
 * 解析歌词工具包
 */
object LyricsUtils {

    /**
     * 解析歌词
     * 将其解析为基于 [LyricsBodyItem] 或 [LyricsStringItem] 的列表
     *
     * @param lyrics
     * @return Pair 前者Boolean代表是否为可滚动的歌词，后者则是歌词分割后的列表
     */
    suspend fun parseLyrics(lyrics: String): Pair<Boolean,List<BaseItemData>>{
        return withContext(Dispatchers.Default){
            if(lyrics.isEmpty()){
                emptyList<BaseItemData>()
            }
            val splitLyrics = lyrics.split("\n")

            if(splitLyrics.isNullOrEmpty()){
                return@withContext Pair(false, emptyList<BaseItemData>())
            }

            val lyricsListAll = mutableListOf<BaseItemData>()

            val canScroll = checkCanScroll(splitLyrics[0])

            if(canScroll){
                for(line in splitLyrics){
                    lyricsListAll.addAll(parseLine(line))
                }
            } else {
                for(line in splitLyrics){
                    lyricsListAll.add(parseStringLine(line))
                }
            }

            canScroll to lyricsListAll
        }
    }

    /**
     * 检测是否是可以滚动的lrc歌词
     * @return true 可滚动 false 不可滚动
     */
    private fun checkCanScroll(line: String): Boolean{
        val matcher = Pattern.compile("((\\[.+])+)(.*)").matcher(line)
        return matcher.matches()
    }

    private fun parseLine(line: String): List<BaseItemData>{
        line.trim().apply {
            val matcher = Pattern.compile("((\\[\\d\\d:\\d\\d\\.\\d+])+)(.+)").matcher(this)
            if(!matcher.matches()){
                return emptyList()
            }

            val times = matcher.group(1) ?: "[00:00.00]"
            val text = matcher.group(3) ?: ""

            val timeMatcher =
                Pattern.compile("\\[(\\d\\d):(\\d\\d)\\.(\\d+)]").matcher(times)

            val lyricsList = mutableListOf<LyricsBodyItem>()
            while (timeMatcher.find()){
                val min = timeMatcher.group(1)?.toLong() ?: 0L
                val sec = timeMatcher.group(2)?.toLong() ?: 0L
                var mil = timeMatcher.group(3)?.toLong() ?: 0L
                if(mil < 100L){
                    mil *= 10
                } else if(mil >= 1000L){
                    mil /= ((mil.toString().length - 3) * 10)
                }
                val time = min * DateUtils.MINUTE_IN_MILLIS + sec * DateUtils.SECOND_IN_MILLIS + mil

                lyricsList.add(LyricsBodyItem(time,false,text))
            }
            return lyricsList

        }
    }

    private fun parseStringLine(line: String): LyricsStringItem{
        return LyricsStringItem(line)
    }
}